home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
THINKC
/
TCL1
/
GRAPH_FO
/
(GRAPH
/
CGRAPHTE
/
CGRAPHPA.C
< prev
next >
Wrap
Text File
|
1991-06-18
|
12KB
|
467 lines
/******************************************************************************
CGraphPane.c
SUPERCLASS = CFontorama.c
This Pane uses some of the Prepare Class Library modifications: WViewTemp()
and implements all necessary modifications to be PCL compatible. If you
have installed the Prepare TCL modifications, you can #define __PCL__.
I have included the code to bypass this.
Copyright ⌐ 1991 Maarten Meijer. All rights reserved.
CIS 100016,1764; FidoNet 2:512/114
*******************************************************************************/
/* defines */
/* #define __PCL__ */ /* see above */
/* includes */
#include <Global.h>
#include <Constants.h>
#include <Commands.h>
#include <CBartender.h>
#include <CDocument.h>
#include <TBUtilities.h>
#include <Commands.h>
#include <CError.h>
#include "GraphCommands.h"
#include "CGraphPane.h"
#include "CMoveTask.h"
#include "CLinkTask.h"
#include "CSelRectTask.h"
/*** Global Variables ***/
extern CBartender * gBartender;
extern short gClicks;
/* methods */
/******************************************************************************
IGraphPane
Initialize a GraphPane object
******************************************************************************/
void CGraphPane::IGraphPane(
CView *anEnclosure,
CBureaucrat *aSupervisor,
short aWidth,
short aHeight,
short aHEncl,
short aVEncl,
SizingOption aHSizing,
SizingOption aVSizing)
{
Point grid;
Rect bounds;
CPanorama::IPanorama(anEnclosure, aSupervisor,
aWidth, aHeight, aHEncl, aVEncl, aHSizing, aVSizing);
SetWantsClicks(true); /* a CView method */
TextFont(geneva); /* allows three digits or letters */
TextSize(9);
SetPt(&grid, 40, 40); /* the Grid */
itsGraph = new(Graph);
itsGraph->IGraph(this, (grHAlign | grVAlign) , grid);
}
/******************************************************************************
IViewTemp {OVERRIDE}
Initialize a Panorama using a template
******************************************************************************/
void CGraphPane::IViewTemp(CView *anEnclosure, CBureaucrat *aSupervisor,
Ptr viewData) {
register GraphPaneTempP p;
short fontID;
p = (GraphPaneTempP) viewData; /* Initialize superclass */
inherited::IViewTemp(anEnclosure, aSupervisor, (Ptr) &p->sPanoramaTemp);
GetFNum(&(p->textFName), &fontID); /* add own variables */
if( RealFont(fontID, p->textSize) ) {
TextFont(fontID);
TextSize(p->textSize);
TextFace(p->textFace);
}
else {
TextFont(geneva);
TextSize(9);
TextFace(0);
}
itsGraph = new(Graph);
itsGraph->IGraph(this, p->flags , p->theGrid);
}
/******************************************************************************
WViewTemp {OVERRIDE}
Write the template data for a Panorama.
This method is include to allow use with the Prepare() TCL Update
(vol 1, issue 3)
******************************************************************************/
void CGraphPane::WViewTemp(Ptr viewData) {
register GraphPaneTempP p;
register GrafPtr grafPtr;
short fontID;
p = (GraphPaneTempP) viewData; /* Set superclass template data */
#ifdef __PCL__
inherited::WViewTemp((Ptr) &p->sPanoramaTemp);
#else
/* CPanorama.c + PCL mods */ /* Set template from instance vars */
((PanoramaTempP)p)->bounds = bounds;
((PanoramaTempP)p)->hScale = hScale;
((PanoramaTempP)p)->vScale = vScale;
((PanoramaTempP)p)->position = position;
/* CPane.c + PCL mods */ /* Set template from instance vars */
((PaneTempP)p)->width = width;
((PaneTempP)p)->height = height;
((PaneTempP)p)->hEncl = hEncl;
((PaneTempP)p)->vEncl = vEncl;
((PaneTempP)p)->hSizing = hSizing;
((PaneTempP)p)->vSizing = vSizing;
((PaneTempP)p)->autoRefresh = autoRefresh;
((PaneTempP)p)->printClip = printClip;
/* CPane.c + PCL mods */ /* Set template from instance vars */
((ViewTempP)p)->visible = visible;
((ViewTempP)p)->active = active;
((ViewTempP)p)->wantsClicks = wantsClicks;
#endif
/*
* add own variables
*/
itsGraph->GetGrid(&p->theGrid);
p->flags = itsGraph->_flags;
grafPtr = GetMacPort();
GetFontName(grafPtr->txFont, &(p->textFName));
p->textSize = grafPtr->txSize; /* ???? */
p->textFace = grafPtr->txFace; /* ???? */
}
/******************************************************************************
GetTempSize {OVERRIDE}
Get the size of the template data for a Panorama.
This method is include to allow use with the Prepare() TCL Update
(vol 1, issue 3)
******************************************************************************/
long CGraphPane::GetTempSize() {
return (long) sizeof(GraphPaneTemp);
}
void CGraphPane::SaveDefault() {
Handle h;
long size;
short refNum;
Point temp, saved;
saved.h = saved.v = 0; /* set the scroll position to zero before */
GetPosition(&temp); /* saving... */
SetPosition(saved);
h = GetResource('GrPn', 128);
CheckResource( h );
refNum = HomeResFile(h);
size = GetTempSize();
SetHandleSize(h, size);
MoveHHi(h);
HLock(h);
WViewTemp( (Ptr) *h );
HUnlock(h);
ChangedResource(h);
WriteResource(h);
UpdateResFile(refNum);
SetPosition(temp); /* restore the saved scroll position */
}
void CGraphPane::Dispose() {
itsGraph->Dispose();
inherited::Dispose();
}
/******************************************************************************
Draw {OVERRIDE}
Draw the contents of the Pane. The area parameter, specified in
the pane's Frame coordinates, indicates the portion of the Pane
which needs to be drawn.
******************************************************************************/
void CGraphPane::Draw(Rect *area)
{
RgnHandle rh;
Rect r = *area;
rh = NewRgn();
GetClip(rh); /* save current clip region */
ClipRect(&r);
itsGraph->Draw(&r);
SetClip(rh); /* restore the clip region */
DisposeRgn(rh);
}
void CGraphPane::DoCommand(long theCommand) {
switch(theCommand) {
case cmdOptions:
itsGraph->SetOptions();
break;
case cmdSetDefault:
SaveDefault();
break;
case cmdDeselectAll:
Prepare();
itsGraph->Deselect(); /* deselect vertexes only for now */
break;
case cmdInstructions:
Prepare();
DrawINST(128);
break;
default:
inherited::DoCommand(theCommand);
break;
}
}
void CGraphPane::UpdateMenus() {
gBartender->EnableCmd(cmdDeselectAll);
gBartender->EnableCmd(cmdInstructions);
gBartender->EnableCmd(cmdSetDefault);
gBartender->EnableCmd(cmdOptions);
gBartender->EnableCmd(cmdFont); /* since hierarchical */
gBartender->EnableCmd(cmdSize);
inherited::UpdateMenus();
}
/******************************************************************************
DoClick {OVERRIDE}
Respond to a mouse click within the view.
All communication with the Graph is via Tasks, either CMouseTasks or
CTasks. MouseTasks are generalized for Graphs in the class CGraphTask.
The following (undoable) actions can be performed:
Adding a Vertex
Removing a Vertex
Adding an Edge (=linking two vertices)
Removing an Edge
Selecting a Vertex or rectangle
Continuing a selection (with the shift key)
Moving the selection (with the option key)
Cutting, Copying or Pasting a selection.
******************************************************************************/
void CGraphPane::DoClick(
Point hitPt,
short modifierKeys,
long when)
{
Point displacement;
Point newCenter;
Rect bounds, area1, area2;
RgnHandle dragRgn;
CGraphTask * task = NULL;
short taskType = 0;
GrVertex * thisVertex = NULL;
GrEdge * thisEdge = NULL;
GrVertex * fromVertex, *toVertex;
itsSupervisor->Notify(NULL); /* Clear old task */
thisVertex = (GrVertex *)itsGraph->FindVertex(hitPt);
if(thisVertex == NULL)
thisEdge = (GrEdge *)itsGraph->FindEdge(hitPt);
if( ((thisVertex == NULL) && (thisEdge == NULL )) ) {
if( !(modifierKeys & shiftKey) )
itsGraph->Deselect();
task = new( CSelRectTask );
taskType = kNoUndoTASK;
}
if((modifierKeys & optionKey) && (thisVertex != (GrVertex *)NULL)) {
if( !(modifierKeys & shiftKey) )
itsGraph->Deselect();
if( thisVertex->Track() != 0 ) {
thisVertex->Select();
SelectConnected();
}
}
else if(modifierKeys & cmdKey) {
itsGraph->Deselect(); /* group removal only with menu ?? */
if(thisVertex != NULL) {
itsGraph->RemoveVertex(thisVertex, TRUE);
}
else if(thisEdge != NULL) {
itsGraph->RemoveEdge(thisEdge, TRUE);
}
else {
itsGraph->AddVertex(hitPt, TRUE);
}
}
else { /* NO modifier keys╔ */
if(gClicks >= 2) {
if(thisVertex != (GrVertex *)NULL) {
Rect r1, r2;
Point p, offset = {0,0};
p = thisVertex->center;
thisVertex->Select();
thisVertex->Draw();
SetRect(&r1, p.h, p.v, p.h, p.v);
GetFrame(&r2);
LocalToGlobal(&offset);
OffsetRect(&r2, offset.h, offset.v);
OffsetRect(&r1, offset.h, offset.v);
ZoomRect(&r1, &r2, true, 1L);
}
else if(thisEdge == (GrEdge *)NULL)
itsGraph->AddVertex(hitPt, TRUE);
}
else {
if(thisVertex != (GrVertex *)NULL) {
if( thisVertex->Selected() ) {
task = new( CMoveTask );
taskType = kMoveTASK;
}
else if( thisVertex->Track() == 0 ) {
if(!(modifierKeys & shiftKey))
itsGraph->Deselect();
task = new( CLinkTask );
taskType = kLinkTASK;
}
else {
if(!(modifierKeys & shiftKey))
itsGraph->Deselect();
thisVertex->ToggleNode(TRUE);
}
}
else if(thisEdge != (GrEdge *)NULL) {
if(thisEdge->Track() != 0) {
if(!(modifierKeys & shiftKey))
itsGraph->Deselect();
thisEdge->fromVertex->ToggleNode(TRUE);
thisEdge->toVertex->ToggleNode(TRUE);
}
}
}
}
if(task) {
task->IGraphTask(taskType, this, itsGraph, hitPt);
Prepare();
GetBounds(&bounds);
/*
* the EndTracking method decides on the Do() and Notify()
*/
TrackMouse(task, hitPt, &bounds);
}
((CDocument *)itsSupervisor)->dirty = TRUE;
}
/******************************************************************************
HitSamePart {OVERRIDE}
Check whether two points hit the same part of the view.
******************************************************************************/
Boolean CGraphPane::HitSamePart(
Point pointA,
Point pointB)
{
GrVertex *vertex;
GrEdge *edge;
register short delta;
if((vertex = itsGraph->FindVertex(pointA)) != NULL)
return vertex->PtInNode(pointB);
else if((edge = itsGraph->FindEdge(pointA)) != NULL)
return edge->PtInNode(pointB);
else if( ( (delta = (pointA.h - pointB.h)) < REASONABLY_CLOSE &&
delta > -(REASONABLY_CLOSE) ) &&
( (delta = (pointA.v - pointB.v)) < REASONABLY_CLOSE &&
delta > -(REASONABLY_CLOSE) ) )
return true;
return false;
}
/******************************************************************************
PrepareToPrint {OVERRIDE}
Set up the proper text font & size as well
*******************************************************************************/
void CGraphPane::PrepareToPrint()
{
CPane::PrepareToPrint();
TextFont(times); /* allows three digits or letters */
TextSize(9);
}
/******************************************************************************
AdjustCursor {OVERRIDE}
Adjust the shape of the cursor according the position of the mouse.
******************************************************************************/
void CGraphPane::AdjustCursor(
Point where, /* Mouse location in Window coords */
RgnHandle mouseRgn) /* Region containing the mouse */
{
extern CursHandle gCrossCursor, gGrabCursor;
SetCursor(*gCrossCursor);
}
/******************************************************************************
ScrollToSelection {OVERRIDE}
Scroll a Panorama so that the current selection is visible within
the frame.
******************************************************************************/
void CGraphPane::ScrollToSelection()
{
}
/******************************************************************************
SelectConnected
*******************************************************************************/
static void SelConnect(GrEdge *this) {
if( this->fromVertex->Selected() ) {
this->toVertex->Select();
this->toVertex->Draw();
}
if( this->toVertex->Selected() ) {
this->fromVertex->Select();
this->fromVertex->Draw();
}
}
void CGraphPane::SelectConnected() {
itsGraph->edgeList->DoForEach(SelConnect);
}